using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;

namespace CKS.EWE.WikiDiscussion
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:WikiDiscussItemButton runat=server></{0}:WikiDiscussItemButton>")]
    public class WikiDiscussItemButton : Microsoft.SharePoint.WebControls.FormButton
    {
        // Create the "Discuss" button used on the Wiki Topic view page.
        // Instance specified in control template SharePoint:RenderingTemplate ID="WikiMiniConsole"
        // string _wikiLib;
        string _discussionLib;
        string _discussionView;
        string _defaultbodytext;

        #region PROPERTIES

        //[Bindable(true)]
        //[DefaultValue("Wiki Pages")]
        //[Localizable(true)]
        //public string WikiPagesLibraryName
        //{
        //    get
        //    {
        //        if (_wikiLib == null) _wikiLib = "Wiki Pages";
        //        return _wikiLib;
        //    }
        //    set
        //    {
        //        _wikiLib = value;
        //    }
        //}

        [Bindable(true)]
        [DefaultValue("Wiki Discussions")]
        [Localizable(true)]
        public string DiscussionLibraryName
        {
            get
            {
                if (_discussionLib == null) _discussionLib = "Wiki Discussions";
                return _discussionLib;
            }
            set
            {
                _discussionLib = value;
            }
        }

        [Bindable(true)]
        [DefaultValue("Flat")]
        [Localizable(true)]
        public string DefaultViewName
        {
            get
            {
                if (_discussionView == null) _discussionView = "Threaded";
                return _discussionView;
            }
            set
            {
                _discussionView = value;
            }
        }

        [Bindable(true)]
        [DefaultValue("This discussion pertains to \"<TopicName>\".")]
        [Localizable(true)]
        public string DefaultBodyText
        {
            get
            {
                if (_defaultbodytext == null) _defaultbodytext = "This discussion pertains to \"<TopicName>\".";
                return _defaultbodytext;
            }
            set
            {
                _defaultbodytext = value;
            }
        }

        private string DiscussionLibraryPath
        {
            get
            {
                return "/Lists/" + DiscussionLibraryName + "/";
            }
        }

        #endregion

        protected override void Render(HtmlTextWriter output)
        {
            SPContext SiteContext = null;
            SPWeb WikiWeb = null;
            SPList WikiPages = null;
            SPListItem WikiPage = null;

            string DiscussionUrl, RootFolder, FolderCTID, TopicsView;
            string rowsetSchema, PageFilename;

            Guid FeatureGuid;
            SPFeature WikiDiscussionFeature = null;

            Guid DiscListGuid, DiscItemGuid;
            string DiscListGuidString, DiscItemGuidString;
            string RootFolderUrl;
            SPList DiscList = null;
            SPListItem DiscItem = null;

            try
            {
                // Get current Site and Web
                SiteContext = SPContext.GetContext(HttpContext.Current);
                WikiWeb = SiteContext.Web;
                WikiWeb.AllowUnsafeUpdates = true;

                // See if the feature is activated by trying to get it. If it's not there, 
                // it's not activated (SPFeatures returns null).  In this case render nothing.
                FeatureGuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom("A0F95442-E28C-41ff-AFB0-C68341C014E7");
                WikiDiscussionFeature = WikiWeb.Site.Features[FeatureGuid];

                if (WikiDiscussionFeature == null)
                {
                    // Check if it's activated at web level.
                    WikiDiscussionFeature = WikiWeb.Features[FeatureGuid];
                }

                if (WikiDiscussionFeature != null)
                {
                    WikiPages = SiteContext.List;
                    WikiPage = SiteContext.ListItem;

                    // GET DISCUSSION LIST

                    // Try to find Wiki Discussions list by Guid stored in Wiki page properties
                    if (WikiPage.Properties["DiscListGuid"] != null)
                    {
                        DiscListGuidString = WikiPage.Properties["DiscListGuid"].ToString();
                        try
                        {
                            DiscListGuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(DiscListGuidString);
                            if (DiscListGuid != Guid.Empty) DiscList = WikiWeb.Lists[DiscListGuid];
                        }
                        catch
                        {
                            // Discussion list previously registerd is no longer there; maybe deleted
                            DiscList = null;
                        }
                    }

                    // Try to find Wiki Discussions list by standard name
                    if (DiscList == null)
                    {
                        try
                        {
                            DiscListGuid = Util.GetListGuid(WikiWeb, DiscussionLibraryName);
                            if (DiscListGuid != Guid.Empty) DiscList = WikiWeb.Lists[DiscListGuid];
                            // Update properties with new GUID
                            if (WikiPage.Properties["DiscListGuid"] != null) WikiPage.Properties.Remove("DiscListGuid");
                            WikiPage.Properties.Add("DiscListGuid", DiscListGuid);
                            WikiPage.Update();
                        }
                        catch
                        {
                            // Discussion list named as feature standard is not there; maybe renamed
                            DiscList = null;
                        }
                    }

                    // Try to find Wiki Discussions list by type (last resort)
                    if (DiscList == null)
                    {
                        try
                        {
                            foreach (SPList list in WikiWeb.Lists)
                            {
                                if (   (list.BaseTemplate == SPListTemplateType.DiscussionBoard) 
                                    && (list.TemplateFeatureId == FeatureGuid) )
                                {
                                    DiscListGuid = list.ID;
                                    DiscList = list;
                                    // Update properties with new GUID
                                    if (WikiPage.Properties["DiscListGuid"] != null) WikiPage.Properties.Remove("DiscListGuid");
                                    WikiPage.Properties.Add("DiscListGuid", DiscListGuid.ToString());
                                    WikiPage.Update();
                                    break;
                                }
                            }
                        }
                        catch
                        {
                            // No discussion list on this site was made from this feature; must have been deleted.
                            DiscList = null;
                        }
                    }
                    if (DiscList == null)
                    {
                        throw new ApplicationException("There is no Wiki Discussions list configured for this site.");
                    }
                    

                    // GET or CREATE DISCUSSION ITEM

                    // If Wiki page has a DiscItemGuid, a Discussion topic has been created already
                    if (WikiPage.Properties["DiscItemGuid"] != null)
                    {
                        DiscItemGuidString = WikiPage.Properties["DiscItemGuid"].ToString();
                        try
                        {
                            DiscItemGuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(DiscItemGuidString);
                            DiscItem = DiscList.Folders[DiscItemGuid];
                        }
                        catch
                        {
                            // No such discussion for this Guid; maybe deleted.  Set null to create new one
                            DiscItem = null;
                        }
                    }

                    // If Discussion topic has not been created for this Wiki topic yet, create one
                    if (DiscItem == null)
                    {
                        PageFilename = Util.rexUrlFilename.Match(WikiPage.Url.ToString()).ToString();
                        PageFilename = Util.rexFilename.Match(PageFilename).Result("$1");

                        // Create new Discussion List item
                        RootFolderUrl = WikiWeb.ServerRelativeUrl + "/" + DiscList.RootFolder.Url;
                        DiscItem = DiscList.Folders.Add(RootFolderUrl, SPFileSystemObjectType.Folder, PageFilename);
                        DiscItem["Title"] = PageFilename;
                        DiscItem["Body"] = "<div>" + Util.ReplaceInBodyText(DefaultBodyText, PageFilename) + "</div>";
                        // ThreadIndex identifies this as the starting posting of a discussion
                        DiscItem["ThreadIndex"] = SPUtility.CreateThreadIndex(null, DateTime.Now);

                        // Save Guids for this Wiki pages list and item so we can return to it from the Discussion.
                        // (It would be easiest to add to Properties collection for the discussion item, as:
                        //     DiscItem.Properties.Add("WikiItemGuid", WikiPage.UniqueId.ToString());
                        //  This works, but has the side effect of changing DiscItem from a folder to an item!
                        //  So, instead we must use custom fields added for this purpose.)
                        DiscItem["WikiListGuid"] = WikiPages.ID.ToString();
                        DiscItem["WikiItemGuid"] = WikiPage.UniqueId.ToString();
                        // Update the Discussion List item
                        DiscItem.Update();

                        // Save Guid for Discussion item so the event handler can coordinate actions (List Guid set above).
                        // (We can use the properties collection for the wiki page item because
                        //  it doesn't have the side effect noted for the discssion folder.)
                        if (WikiPage.Properties["DiscItemGuid"] != null) WikiPage.Properties.Remove("DiscItemGuid");
                        WikiPage.Properties.Add("DiscItemGuid", DiscItem.UniqueId.ToString());
                        // Update the Wiki Pages item
                        WikiPage.Update();
                    }


                    // RENDER DISCUSS BUTTON

                    // Build Discussion list item URL
                    DiscussionUrl = WikiWeb.Url + DiscussionLibraryPath + DefaultViewName + ".aspx";
                    RootFolder = SPEncode.UrlEncode(WikiWeb.ServerRelativeUrl + "/" + DiscItem.Url);
                    TopicsView = SPEncode.UrlEncode(WikiWeb.Url + DiscussionLibraryPath + "AllItems.aspx");

                    // Retrieve the ContentID of the folder; e.g. "0x01200200B1860303A3FB3544B47B5CEE6DEA852B"
                    // It's the same for all folders in this list, but unique per each new list instance. 
                    // The only place I can find it now is in DiscList.Folders.XmlDataSchema.  Could extract
                    // it using an XPATH query but we're not sure of potential namespace changes, so we'll
                    // just get it as a string and extract it with a regular expression.
                    rowsetSchema = DiscList.Folders.Xml.ToString();
                    if (Util.rexCTID.Match(rowsetSchema).Success)
                    {
                        FolderCTID = Util.rexCTID.Match(rowsetSchema).Result("$1");
                    }
                    else
                    {
                        // Try the base content ID (folder)
                        FolderCTID = "0x012002";
                    }

                    // Render the sucker
                    RenderButton(output, DiscussionUrl + "?RootFolder=" + RootFolder + "&FolderCTID=" + FolderCTID + "&TopicsView=" + TopicsView);
                }

            }
            catch (Exception ex)
            {
                Util.LogException(output, ex);
            }

            finally
            {
                if (WikiWeb != null)
                {
                    //WikiWeb.Dispose();
                }
            }
        }


        protected void RenderButton(HtmlTextWriter output, string encodedURL)
        {
            // Render the button.  Most properties of this button come from the control
            // template WikiTopicTemplate.ascx or WikiDiscussionTemplate.  The destination URL is
            // computed to match the appropriate discussion topic, and passed to this routine.
            string altText;

            output.Write("<table cellpadding='1' cellspacing='0'");
            if (this.ToggleOn)
            {
                output.Write(" class='ms-toolbar-togglebutton-on'");
            }
            output.Write(">");
            output.Write("<tr>");

            if (string.IsNullOrEmpty(this.ToolTip))
            {
                altText = base.Text;
            }
            else
            {
                altText = this.ToolTip;
            }

            output.Write("<td class='ms-toolbar' nowrap");
            if (!string.IsNullOrEmpty(this.Padding))
            {
                output.Write(" style=\"padding: ");
                output.Write(SPHttpUtility.HtmlEncode(this.Padding));
                output.Write("\"");
            }
            output.Write(">");

            output.Write("<a ");
            output.Write(" href='" + encodedURL + "'");
            output.Write(" class='ms-toolbar'");
            output.Write(">");

            RenderImage(output, altText, "width='16' height='16'"); //render this.ImageURL if specified
            output.Write("</a>");
            output.Write("</td>");

            output.Write("<td class='ms-toolbar' nowrap");
            if (!string.IsNullOrEmpty(this.Padding))
            {
                output.Write(" style=\"padding: ");
                output.Write(SPHttpUtility.HtmlEncode(this.Padding));
                output.Write("\"");
            }
            output.Write(">");

            output.Write("<a ");
            output.Write(" href='" + encodedURL + "'");
            output.Write(" class='ms-toolbar'");
            output.Write(" title='" + altText + "'");
            output.Write(">");

            output.Write(base.Text);
            output.Write("</a>");
            output.Write("</td>");

            output.Write("<td class=ms-separator>|</td>");

            output.Write("</tr></table>");
        }
    
    }
}
